function isNumeric(c) {
  return c >= "0" && c <= "9";
  // return (
  //   c === "0" ||
  //   c === "1" ||
  //   c === "2" ||
  //   c === "3" ||
  //   c === "4" ||
  //   c === "5" ||
  //   c === "6" ||
  //   c === "7" ||
  //   c === "8" ||
  //   c === "9"
  // );
}

export function* lexer(file, str) {
  let line = 1;
  let column = 1;
  let cursor = 0;
  let char = str[cursor];

  console.log("lexer:", char);
  const next = () => {
    cursor++;
    char = str[cursor];
    console.log("lexer:", char);
    column++;
  };

  const newline = () => {
    line++;
    column = 1;
  };

  const number = () => {
    let buffer = "";

    while (isNumeric(char)) {
      // TODO 符合的语法组合起来
      buffer += char;

      next();
    }

    if (buffer.length >= 1) {
      return {
        type: "NumbericLiteral",
        value: Number(buffer),
      };
    }

    return null;
  };

  const operator = () => {
    if (char === "+") {
      next();

      return {
        type: "PlusToken",
        // value: "+",
      };
    }

    return null;
  };

  const isWhitespace = (c) => {
    return c === " " || c === "\t";
  };

  const whitespace = () => {
    if (isWhitespace(char)) {
      next();
    } else {
      return null;
    }

    // while (isWhitespace(char)) {
    //   next();
    // }

    return true;
  };

  const eol = () => {
    if (char === "\n") {
      next();
      newline();
    } else {
      return null;
    }

    // while (char === '\n') {
    //   next();
    //   newline();
    // }

    return true;
  };

  const eof = () => {
    if (char === undefined) {
      return {
        type: "EndOfFileToken",
        // value: undefined
      };
    }
    return null;
  };

  for (;;) {
    const token = whitespace() || operator() || number() || eol();

    if (token) {
      if (token === true) {
        continue;
      }

      yield token;

      continue;
    }
    
    const maybeEof = eof();
    if (maybeEof) {
      yield maybeEof;
      break;
    }

    // 找到不符合的语法
    // throw new SyntaxError(`Unexpected character "${char}" at ${cursor + 1}`);
    throw new SyntaxError(
      `Unexpected character "${char}" at ${file} ${line}:${column}`
    );
  }
}
